package com.yc.javaee;

import com.yc.javaee.tomcat.*;
import com.yc.javaee.tomcat.impl.*;

import javax.servlet.annotation.WebServlet;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 响应报文
 * 头域
 * 头行: 协议版本(空格)结果码(空格)结果码说明
 * 头域参数: N行键值对
 * CRLF 空行
 * 实体区
 * 内容
 * 结果码:
 * 1xx : 接收请求继续处理
 * 2xx : 成功 200
 * 3xx : 响应重定向   301, 302
 * 4xx : 浏览器端错误  404, 405
 * 5xx : 服务器端错误  500, 503
 */
public class Tomcat服务器 implements Tomcat {

    public static final String WEBROOT = "D:\\_文件柜\\112\\C122-S2-Ply-JavaEE\\src\\main\\webapp\\photo";
    // 会话容器
    public static final Map<String,HttpSession> sessionMap = new HashMap<>();

    public static void main(String[] args) throws IOException {
        //java.net.BindException: Address already in use: JVM_Bind
        // 端口冲突, 改端口     80=>http协议默认端口
        new Tomcat服务器().start(80);
    }

    // Servlet容器
    private Map<String,HttpServlet> servletMap = new HashMap<>();
    // 初始化Servlet容器
    public void initServletMap() throws InstantiationException, IllegalAccessException {
        // 扫描功能内, 所有被标注 @WebServlet 注解的类
        Class<HttpServlet>[] servlets = new Class[]
                {HelloServlet.class, RedirectServlet.class,
                        CookieServlet.class,
                        SessionServlet.class,
                        LoginServlet.class,
                LogoutServlet.class, getLoginedUserServlet.class};
        for (Class<HttpServlet> servletClass : servlets) {
            // Java 反射技术
            HttpServlet servlet = servletClass.newInstance();// 创建对象 ==> new HelloServlet();
            WebServlet webServlet = servletClass.getAnnotation(WebServlet.class);// 获取类名上的 WebServlet 注解对象
            // webServlet.value()[0] ==> 获取注解中配置的地址  例如: /hello.s
            servletMap.put(webServlet.value()[0], servlet);
            // 初始化serlvet
            servlet.init();
        }
    }

    @Override
    public void start(int port) {
        try {
            ServerSocket server = new ServerSocket(port);
            System.out.println("服务器启动完成, 监听" + port);
            // 初始化serlvet容器
            initServletMap();

            for (; ; ) {
                Socket socket = server.accept();
                // 构建请求对象
                HttpServletRequest request = buildRequest(socket);
                // 构建响应对象
                HttpServletResponse response = buildResponse(socket, request);

                if (isStaticRequest(request)) {
                    // 处理静态请求
                    processStaticRequest(request, response);
                } else if (isServletRequest(request)) {
                    // 处理动态请求
                    try {
                        processServletRequest(request, response);
                    } catch (ServletException e) {
                        e.printStackTrace();
                    }
                } else {
                    // 返回 404 错误响应
                }
                socket.close();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public HttpServletRequest buildRequest(Socket socket) {
        try {
            return new HttpServletRequestImpl(socket);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public HttpServletResponse buildResponse(Socket socket, HttpServletRequest request) {
        try {
            return new HttpServletResponseImpl(socket, request);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean isStaticRequest(HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String filepath = WEBROOT + requestURI;
        return new File(filepath).exists();
    }

    @Override
    public boolean isServletRequest(HttpServletRequest request) {
        // 判断容器是否包含该请求的地址
        return servletMap.containsKey(request.getRequestURI());
    }

    @Override
    public boolean processStaticRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setStatus(200,"OK");
        String contentType = getMimeType(request.getRequestURI());
        response.setContentType(contentType);
        response.flushBuffer();
        return true;
    }

    @Override
    public boolean processServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 在推送数据之前, 将会话id存入到cookie中
        String sessionId = request.getSession().getId();
        Cookie cookie = new CookieImpl("JSESSIONID", sessionId);
        response.addCookie(cookie);
        // 根据地址查找servlet 对象
        HttpServlet httpServlet = servletMap.get(request.getRequestURI());
        // 执行业务方法
        httpServlet.service(request,response);
        // 将结果输出到浏览器
        response.flushBuffer();
        return true;
    }

    @Override
    public String getMimeType(String path) {
        path = path.toLowerCase();
        if (path.endsWith(".js")) {
            return "application/javascript;charset=utf-8";
        } else if (path.endsWith(".css")) {
            return "text/css;charset=utf-8";
        } else if (path.endsWith(".jpg")) {
            return "image/jpg";
        } else if (path.endsWith(".png")) {
            return "image/png";
        } else if (path.endsWith(".gif")) {
            return "image/gif";
        } else if (path.endsWith(".bmp")) {
            return "image/bmp";
        } else {
            return "text/html;charset=utf-8";
        }
    }

    @Override
    public HttpServlet getServlet(HttpServletRequest request) {
        return null;
    }

    @Override
    public void createSession(HttpServletRequest request, HttpServletResponse response) {

    }

    @Override
    public void stop() {

    }
}
